

package Game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.Timer;

/**
 *
 * Compiler: jdk1.6.0_14 <br />
 * IDE: NetBeans 6.7.1 <br />
 * @author Andrew Smith <br />
 */
public class Shot
{
    /** the tank who shot this shot */
    private Tank owner;
    /** the direction this shot is travelling in */
    private Direction direction;
    /** the current x position of the shot */
    private int shotX;
    /** the current y position of the shot */
    private int shotY;
    /** the total distance traveled */
    private int totalDistance;
    /** true if the shot is currently still shooting */
    private boolean isShooting;
    /** the maximum distance this shot can travel */
    private static final int MAX_DISTANCE = 250;
    /** the timer that this shot is moving to */
    private Timer timer;
    /** the ms that the timer is refreshing */
    private static final int TIMER_REFRESH = 35;

    /** holds all the listeners listening to this shot */
    private ArrayList<ActionListener> listeners;


    /**
     * Creates a new shot from a tank.
     * @param owner the tank who shot this.
     * @param direction the direction it is traveling in
     * @param startX the start x coordinate of this shot
     * @param startY the start y coordinate of this shot
     */
    public Shot(Tank owner, Direction direction, int startX, int startY)
    {
        this.owner = owner;
        this.direction = direction;
        this.shotX = startX;
        this.shotY = startY;
        isShooting = true;
        totalDistance = 1;
        listeners = new ArrayList<ActionListener>();
        startTimer();
    }

    /**
     * Sets up and starts the timer
     */
    private void startTimer()
    {
        timer = new Timer(TIMER_REFRESH, new TimerListener());
        timer.start();
    }

    /**
     * Gets the x position
     * @return
     */
    public int getX()
    {   return shotX;
    }

    /**
     * Gets the Y position
     * @return
     */
    public int getY()
    {   return shotY;
    }

    /**
     * Gets the tank who shot this shot
     * @return
     */
    public Tank getOwner()
    {   return owner;
    }

    /**
     * Gets if the shot is shooting at the moment
     * @return
     */
    public boolean isShooting()
    {   return isShooting;
    }

    /**
     * Called when if the shot hits an obstacle (ie like a rock)
     */
    public void hitObstacle()
    {
        stopShot(HIT_OBSTACLE_MESSAGE);
    }

    /**
     * Called when if the shot hits a player/tank
     * @param victim the tank that it hit
     */
    public void hitTank(Tank victim)
    {
        stopShot(HIT_PLAYER_MESSAGE);
    }

    /** this is the multiplyer for the distance the shot moves */
    private static final int movement_multiplyer = 4;
    
    
    /**
     * Moves the shot
     */
    private void moveShot()
    {
        Point newValue = direction.getNextPointValue();
        shotX += newValue.x * movement_multiplyer;
        shotY += newValue.y * movement_multiplyer;

        totalDistance += movement_multiplyer;
    }


    /**
     * Stops the shot from shooting
     * @param message the message as to why it has stopped shooting
     */
    private void stopShot(String message)
    {
        timer.stop();
        isShooting = false;
        notifyListeners(message);
    }


    private static final int SHOT_DIA = 8;

    /**
     * Draws this shot on the graphics passed to it
     * @param g
     */
    public void draw(Graphics g)
    {
        if(isShooting)
        {   g.setColor(Color.RED);
            g.fillOval(shotX-(SHOT_DIA/2), shotY-(SHOT_DIA/2), SHOT_DIA, SHOT_DIA);
        }
        
    }


    /**
     * Adds a new listener onto this to check for updates
     * @param listener the listener to watch this shot
     */
    public void addActionListener(ActionListener listener)
    {
        listeners.add(listener);
    }

    /** an update id for actionevents */
    private int update_id = 0;
    //valid messages for the notifyListeners method
    public static final String MOVING_MESSAGE = "moving";
    public static final String HIT_OBSTACLE_MESSAGE = "obstacle";
    public static final String HIT_PLAYER_MESSAGE = "player";
    /**
     * Notifies all the listeners with this
     */
    private void notifyListeners(String message)
    {
        for(int i=0; i<listeners.size(); i++)
        {
            update_id++;
            ActionEvent e = new ActionEvent(this, update_id, message);
            
            if(listeners.get(i)!=null)
            {   listeners.get(i).actionPerformed(e);
            }
        }
    }

    /**
     * Makes sure the shot is still on screen
     * @return
     */
    private boolean isOnScreen()
    {
        if(this.shotX > 0 && this.shotX < Match.BOUNDS_WIDTH)
        {   if(this.shotY > 0 && this.shotY < Match.BOUNDS_HEIGHT)
            {   return true;
            }
        }
        return false;
    }



    /**
     * Inner class to listen for updates when the timer is on
     */
    private class TimerListener implements ActionListener
    {

        public void actionPerformed(ActionEvent e)
        {
            if(e.getSource() == timer)
            {
                if(totalDistance > MAX_DISTANCE || !isOnScreen())
                {
                    stopShot(HIT_OBSTACLE_MESSAGE);
                }
                else
                {
                    moveShot();
                    notifyListeners(MOVING_MESSAGE); //notifies anyone who wants to listen that the shot has been moved
                }
            }
        }

    }
}
